
local skynet = require "skynet"
local log = require "Log"
local config = require "configquery"
local Timer = require "timer"
local FSM = require "fsm"
local NodeMessage = require "NodeMessage"
local Universal = require "Universal"
local json = require "cjson"
require "common"

local gameName = 'mahjong'
local inspect = require "inspect"

local Player = require (gameName..".player")
local event = require (gameName..".event")
local event_priority_queue = require (gameName..".event_priority_queue")
local card = require (gameName..".card")
local ting_pai = require (gameName..".changsha_ting")
local mix_array = mix_array
local table_clone = table_clone
local floor = math.floor
local four_five = math.four_five
local random = math.random

local MachineBase = require "common.MachineBase"
local Machine = class("Machine",MachineBase)

local tblog_version = "100"

local HU = 4
local GANG = 3
local PENG = 2
local CHI = 1

function Machine:ctor(tableid,rule)
	json.encode_sparse_array(true)
	self.super:ctor(tableid,rule) --父类
	self.data = {}

	self.room_flag = ""..self.tableid..os.time()--大局唯一标识

	-- local data = self.nodeMessage:callService('dbmgr_service','reload_private_tables',tableid)
	local sql = string.format("select * from private_tables where tableid = %d", tableid)
	local data = skynet.call("mysql_service", "lua", "execute", sql)
	data = data[1]	
	local setting = json.decode(data.setting)

	self.config = {}
	self.config.play_count = setting.play_count or 8--最大局数
	self.config.pay_type = setting.payer or 1--支付类型
	self.config.verify_code = data.number or 1--房号
	self.config.owner = data.managerid --房主id
	self.config.vote_time = 120 --投票时间
	self.config.cost = setting.cost or 0--花费
	self.config.player_num = setting.player_num or 4 --人数
	self.config.base_score = 1
	self.config.fish_num = setting.fish_num or 8
	self.config.hai_di_hu = setting.haidihu or 0
	self.config.gang_yao_num = setting.gang_yao_num or 2
	self.config.lose_type = setting.lose_type or 1
	self.vote = {}
	self.vote.tbCloseVote = {} --请求解散桌子
	if self.config.pay_type==2 then --aa付
		self.config.cost = math.floor(self.config.cost/self.config.player_num)
	end

	self.handlerVoteTime = nil --解散桌子定时器
	self.sourceid = nil --发起者id

	self.data.ordinal = 0
	self.data.total_result = {{},{},{},{}}

	self.waitTime = 0 --桌子等待开始的时间 
	self.closeVoteTime = 90
	self.voteTime = 120 --投票时间
	self.player_state = {		
		playing = 1, --正常
		auto 	= 2, --托管		
		ready 	= 3, --已准备
		disconnect = 4, --离线		
	}

	self.status_time = {
		wait 			= 1,	--等待时间
		rest 			= 5,	--休息时间
		start 			= 10,	--开始
		oper 			= 30,	--出牌操作时间	
		lastcard 		= 2,	--最后一手出牌时间	
		settle			= 1, 	--结算时间
	}

	self.time = {
		close_room_time = 60 * 10,
	}

	self.game_status = {
		STATE_DEAL_POKER 		= 1,
		STATE_WAIT_XIAOHU 		= 2,
		STATE_WAIT_TIANHU 		= 3,
		STATE_WAIT_PLAY 		= 4,
		STATE_WAIT_RESPONSE 	= 5,
		STATE_TAKE_CARD			= 6,
		STATE_HAI_DI			= 7,
		STATE_GAME_OVER	 		= 8,
		STATE_GANG_YAO	 		= 9,
	}

	self:reset()

--[[
	--状态
	--wait  rset  start  wait_play wait_response settle tian_hu di_hu xiao_hu
]]
	local gameStateTransitionTable = {
		{"rest", 		"to_start", 			"start", 		function() self:on_start() end },
		{"wait", 		"to_rest", 				"rest", 		function() self:on_rest() end},	
		{"start", 		"to_rest", 				"rest", 		function() self:on_rest() end},
		{"rest", 		"to_wait", 				"wait", 		function() self:on_wait() end},
		{"settle", 		"to_rest", 				"rest", 		function() self:on_rest() end},
	}

	self.fsm = FSM.new(gameStateTransitionTable)

	local tbStateTransitoin = {
		{"rest", 		"to_start", 			"start", 		function() self:onStartVote() end },
		{"start", 		"to_end", 				"end", 			function() self:onEndVote() end },
		{"start", 		"to_rest", 				"rest", 		function() self:onRestVote() end },
	}
	--状态机
	self.fsm2 = FSM.new(tbStateTransitoin)
	self.fsm2:set("rest")
end

local function table_copy_table(ori_tab)
	if (type(ori_tab) ~= "table") then
		return nil
	end
	local new_tab = {}
	for i,v in pairs(ori_tab) do
		local vtyp = type(v)
		if (vtyp == "table") then
			new_tab[i] = table_copy_table(v)
		elseif (vtyp == "thread") then
			new_tab[i] = v
		elseif (vtyp == "userdata") then
			new_tab[i] = v
		else
			new_tab[i] = v
		end
	end
	return new_tab
end

function Machine:on_start() 
	log.debug("进入on_start,发牌阶段")
	self.operStartTime = os.time()
	self:set_game_state(self.game_status.STATE_DEAL_POKER)
	--更新每个玩家的状态
	for seatid,playerid in pairs(self.seat_list) do 
		player = self.player_list[playerid]
		if player.ready then 
			player.playing = true
		end
		player.noReadyTime = 0
	end

	self.game.log.game_config = {
		start_time=os.time(),		
		end_time=os.time(),
		card_num=14, 
		jushu=self.config.play_count or 1,
		cur_jushu=self.config.play_count or 1,
		payer=self.config.pay_type or 1,
		roomid=self.config.verify_code or 1,
		owner=self.config.owner or 1, 
		play_type=self.config.lose_type or 1,
	}

	self.data.ordinal = self.data.ordinal + 1
	self.waitTime = 0

	math.randomseed(os.time())
	self:generate_dealer(seatid)
	self:construct_set()
	local x,y = self:get_card_dice() --骰子
	self:deal_card(x,y)

	local callback2 = function ( )		
			self:enter_xiao_hu()
		end
	timehandler = self.timer:register(3,nil,callback2)
	return 
end

--重置数据
function Machine:reset()
	--玩家的数据
	self.player = {}
	for i=1,self.config.player_num do
		self.player[i] = Player.new(self)
		self.player[i]:init()
	end
	--游戏数据
	self.game = {}
	self.game.play_log_str = {} --牌局日志
	self.game.check_tianhu = false
	self.game.check_dihu = false
	self.game.touzi ={} --骰子的点数
	self.game.dealer = self.data.last_win or math.random(1,self.config.player_num)
	self.game.recent_play = {}
	self.game.log = {version = tblog_version,start = {},play = {} ,result = {},game_config = {}}
	--各种分数
	self.game.status = self.game_status.STATE_GAME_OVER
	self.game.cancel_action = {}
	for i=1,self.config.player_num do
		self.game.cancel_action[i] = {}
	end

	self.game.gang_yao_data = {}
	self.game.gang_yao_data.player = {}
end

--休息
function Machine:on_rest()
--	log.debug("进入on_rest,休息阶段")
	self.operStartTime = os.time()
	--洗牌
	
	--重置数据
	self:reset()
	--通知客户端

	local function  checkPlayer()
		--人数足3个才开始
		local num = self:getReadyNum()
		if self.fangkaEnd then 
			return 
		end
		-- if num < self.config.player_num or self.handlerVoteTime  then 
		-- 	self.fsm:fire("to_wait")
		-- 	return false
		-- end	
		if self.data.ordinal == self.config.play_count then 
			--总结算
			self:nt_total_result()
			return false
		end
		if num < 4 or self.handlerVoteTime  then 
			self.fsm:fire("to_wait")
			return false
		end	
		if self.close then --已关服
			return false
		end
		self.fsm:fire("to_start")
		return true
	end
	if not checkPlayer() then 
		return 
	end

end

function Machine:on_wait()
	--log.debug("进入on_wait,等待阶段")
	local timehandler = nil
	local callback = function()
		if timehandler then
			return 
		end
		-- self:removeDisconnect()
		--self:removePlayer()
		--人数足2个才开始
		local num = 0
		local robotNum = 0
		for k,v in pairs(self.player_list) do
			if v.noReadyTime then
				v.noReadyTime = v.noReadyTime + self.status_time.wait
				if v.noReadyTime > 10 then 
					--清除没准备的玩家
					v.noReadyTime = 0
				end
			end		
			if v.ready then 		
				num = num + 1
			end
		end
		if self.data.ordinal == 0 then 
			self.waitTime = self.waitTime + self.status_time.wait
			if self.waitTime>self.time.close_room_time then
				--没有开始10分钟后解散桌子
				log.debug("时间到没开始解散桌子",self.tableid,self.config.owner)
				self.waitTime = 0
				self:deleteTable(self.config.owner)
			end
		end

		if num < 4 then 
			--return
		end		
		--
		local callback2 = function ( )		
			self.fsm:fire("to_rest")			
		end
		timehandler = self.timer:register(self.status_time.wait,nil,callback2)
				
	end
	self:setTime(self.status_time.wait,callback,true)
end

function Machine:time_out_xiao_hu( ... )
	
end

function Machine:enter_xiao_hu()
	log.debug("进入 on_xiao_hu,检测小胡阶段")
	self:set_game_state(self.game_status.STATE_WAIT_XIAOHU)
	local enter_next_status = true
	for i=1,#self.player do
		local t = self:check_xiao_hu(i)
		if t then
			--通知玩家小湖 直接算分/////并加入优先级队列?
			local ret = {xiaohu = true}
			self:send_can_reponse_message(i,ret)
			self.player[i]:set_action_can_do(ret)

			enter_next_status = false
		end
	end
	log.debug("Machine:enter_xiao_hu",self.game.xiao_hu)
	if enter_next_status then
		return self:enter_tian_hu_state()
	else
		--设置定时器 到时自动胡牌处理
		local callback = function()
			self.game.xiao_hu = nil
			self:enter_tian_hu_state()
		end
		self:setTime(self.status_time.oper,callback)
	end
end

function Machine:enter_tian_hu_state()
	log.debug("进入 on_tian_hu,检测天胡阶段")
	self:set_game_state(self.game_status.STATE_WAIT_TIANHU)
	self.game.check_tianhu = true
	local t = self:check_tian_hu()

	if not t then
		--进入下一个阶段
		self.game.check_tianhu = false
		self.game.check_dihu = true
		self.game.first_card = true
		--将庄家最后一张牌设为本局刚拿的牌
		local set = self.player[self.game.dealer]:get_set()
		local c = table.remove(set)
		--self.game.deal_target = self.game.dealer
		if not self.game.recent_play then
			self.game.recent_play = {}
		end
		self.game.recent_play.target = self.game.dealer
		self.game.recent_play.card = c

		self.player[self.game.dealer]:set_this_turn_get(c)

		return self:deal_player_take_card(self.game.recent_play.target,c)
	end
	--通知玩家天湖
	--设置定时器胡牌 到时自动胡牌处理
	local ret = {tianhu = true}
	self:send_can_reponse_message(self.game.dealer,ret)
	self.tianhu = t

	local callback = function()
		self:timeout_dealer_confirm_tian_hu()
	end
	self:setTime(self.status_time.oper,callback)
end

function Machine:timeout_dealer_confirm_tian_hu()
	self:calculate_result(self.tianhu)
end

function Machine:enter_wait_play_state(target)
	log.debug("进入 on_wait_play,出牌阶段 出牌位置:",target)
	--local target = self.game.turn or self.game.dealer
	--等待玩家出牌状态
	self:set_game_state(self.game_status.STATE_WAIT_PLAY)
	self.game.cancel_action[target] = {}
	local plr = self.player[target]
	self.game.turn = target   --摸牌的玩家

	self.game.qiang_gang = false
	
	if card:has(self.game.gang_yao_data.player,target) then
		local callback = function()
			self:time_out_auto_play(target)
		end
		self:setTime(1,callback)
		return
	end

	if not self:getPlayerBySeat(target) then
		local callback = function()
			self:time_out_auto_play(target)
		end
		self:setTime(1,callback)
		return
	end

	if self:get_left_card_num() < 1 then
		log.debug("海底胡 定时器出牌 1s后自动出牌")
		local callback = function()
			self:time_out_auto_play(target)
		end
		self:setTime(2,callback)
		return
	end

	--设置定时器胡牌 到时自动出牌
		local callback = function()
			self:time_out_auto_play(target)
		end
		self:setTime(self.status_time.oper,callback)
end

--如果杠摇有杠 且两个不同的人杠 怎么处理?????
function Machine:enter_gang_yao_wait_reponse_card_state(tgt,cards)
	log.debug("进入 gang_yao_wait_reponse(杠摇公共回合),等待响应阶段")
	self:set_game_state(self.game_status.STATE_WAIT_RESPONSE)
	for i,v in ipairs(self.player) do
		self.player[i]:set_action_can_do({})
	end

	
	self.game.gang_yao_data.handle_cards = cards
	self.game.card_discard_from = tgt
	local cards_num = #cards
	local e_p_q = event_priority_queue.new()
	e_p_q:ctor()
	self.e_p_q = e_p_q
	local target = tgt
	for k,c in pairs(cards) do	
		for i=1,#self.player - 1 do
			target = target%#self.player + 1
			local  t = self.player[i]:get_action_can_do()
			self.player[target].evts = {}
			if not self.game.cancel_action[target].hu then
				t.hu = self:check_hu(target,c)
			end
			------------------------------------------
			if (self:get_left_card_num() > 0 ) then
				t.bu = self:check_gang(target,c) 
				--这里杠和补字段名要换下
				local ting = self:get_ting_data(target,c)
				if next(ting) and t.gang then
					t.gang = true
				end
				t.peng = self:check_peng(target,c) 
				if i == 1 then
					t.chi = self:check_chi(target,c)
				end
			end
			self.player[target]:set_action_can_do(t)
			--通知前端对应操作
			if k == cards_num and next(t) then
				self:send_can_reponse_message(target,t)
			end
		end
	end
	if e_p_q:size() == 0 then
		--进入下一个玩家摸牌阶段
		return self:player_take_card(tgt%#self.player + 1)
	end
	e_p_q:sort()
	--设置定时器胡牌 到时自动处理
	log.debug("e_p_q",inspect(e_p_q))

	local callback = function()
			self:wait_reponse_time_out(tgt)
		end
		self:setTime(self.status_time.oper,callback)
	return 
end

function Machine:enter_wait_reponse_card_state(tgt,c)
	log.debug("进入 on_wait_response(公共回合),等待响应阶段")
	self:set_game_state(self.game_status.STATE_WAIT_RESPONSE)
	for i,v in ipairs(self.player) do
		self.player[i]:set_action_can_do({})
	end
	self.game.card_discard_from = tgt

	local e_p_q = event_priority_queue.new()
	e_p_q:ctor()
	self.e_p_q = e_p_q
	local target = tgt

	for i=1,#self.player - 1 do
		target = target%#self.player + 1
		local  t = {}
		self.player[target].evts = {}
		if self:getPlayerBySeat(target) and not self.game.cancel_action[target].hu then
			t.hu = self:check_hu(target,c)
		end
		------------------------------------------if card:has(self.game.gang_yao_data.player,target) then
		if not card:has(self.game.gang_yao_data.player,target) and (self:get_left_card_num() > 0 ) and self:getPlayerBySeat(target) then
			t.bu = self:check_gang(target,c) 
			--这里杠和补字段名要换下
			local tb = {}
			local plr = self.player[target]
			tb.set = plr:get_set_ex(c)
			tb.all_set = plr:get_all_card()
			tb1 = {}
			tb1.need_258 = ( plr:need_258())
			tb1.chi = plr:is_chi()

			if t.bu and next(ting_pai:check_ting(tb,tb1))  then
				t.gang = true
			end
			t.peng = self:check_peng(target,c) 
			if i == 1 then
				t.chi = self:check_chi(target,c)
			end
		end
		self.player[target]:set_action_can_do(t)
		--通知前端对应操作
		if next(t) then
			self:send_can_reponse_message(target,t)
		end
	end
	if e_p_q:size() == 0 then
		--进入下一个玩家摸牌阶段
		return self:player_take_card(tgt%#self.player + 1)
	end
	e_p_q:sort()
	--设置定时器胡牌 到时自动处理
	log.debug("e_p_q",inspect(e_p_q))

	local callback = function()
			self:wait_reponse_time_out(tgt)
		end
		self:setTime(self.status_time.oper,callback)
	return 
end

function Machine:player_take_card(target)
	log.debug("进入 on_take_card(公共回合),摸牌阶段 下一个摸牌玩家为",target)

	if target == self.game.dealer then
		self.game.check_dihu = false		
	end
	self.game.turn = target
	self.game.qiang_gang = false
	self.game.gang_shang_flower = 0
	local c = self:take_card_from_start(target)
	if not c then
		return 
	end
	return self:deal_player_take_card(target,c)
end

function Machine:enter_hai_di(target)
	self:set_game_state(self.game_status.STATE_HAI_DI)
	self.game.hai_di = {}
	--local target = self.game.turn%#self.player + 1
	log.debug("进入 on_hai_di(海底胡询问)阶段  第一位玩家",target)
	self.game.hai_di.first =  target
	self.game.hai_di.last_get = 0
	self.game.hai_di.target = target


	return self:deal_hai_di(target)
end

function Machine:deal_hai_di(target)

	--发送消息给前端(有个问题, 没有如果超时处理的话 前端不知道我这边处理了)

	self:send_hai_di_message(target)

	--超时处理
	local callback = function()
		self:time_out_hai_di(target)
	end
	local time = self.status_time.oper
	if not self:getPlayerBySeat(target) then
		time = 1
	end
	self:setTime(time,callback)
end

function Machine:time_out_hai_di(target)

	local next_target = target%#self.player + 1

	log.debug("超时 处理海底胡 超时玩家",target,"下一个询问的玩家",next_target)
	if next_target ~= self.game.hai_di.first then
		return self:deal_hai_di(next_target)
	end
	return self:calculate_result()
end

function Machine:calculate_xiaohu_score(result,base_score)
	local score_result = {}
	local winner_score = 0
	if result.card_from == 0 then
		local other = result.user
		local score = base_score
		for i=1,#self.player - 1 do
			other = other%#self.player + 1
			score = base_score
			score = score * (0 + 1)
			winner_score = winner_score + score
			self.player[other]:add_score(- score)
			score_result[other]= - score
		end
		score_result[result.user] = winner_score
		self.player[result.user]:add_score(winner_score)
	end
	return score_result
end

function Machine:calculate_xiaohu_result( target )
	local result = self.game.xiao_hu[target]
	if not self.game.xiao_hu_socre then
		self.game.xiao_hu_socre = {0,0,0,0}
	end


	--积分
	local base_score = #result.tp
	
	--计算小胡分数
	local score_result = self:calculate_xiaohu_score(result,base_score)

	for k,v in pairs(score_result) do
		self.game.xiao_hu_socre[k] = self.game.xiao_hu_socre[k] + v

		local player = self:getPlayerBySeat(k)
		if player then
			player.chip = player.chip + v
		end
	end

	--清除胡牌
	if result.user == target then
		self.game.xiao_hu[target] = nil
	end
	--通知
	local hu_type = self:get_xiao_hu_type(result.tp)

	local ret = {
		mj_xiao_hu_result_res={
			seatid=result.user ,
			set =  result.set ,
			hu_type = hu_type,
			score = base_score,
			card_from = result.card_from,
			score_result = score_result
		}
	}
	self:log_error(ret)
	self:sendToAll(ret)
	local total_result = {}
	if result.card_from == 0 then
		total_result[result.user] = {}
		total_result[result.user].xiaohu_zimo = 1
	else
		total_result[result.user] = {}
		total_result[result.user].xiaohu_hu = 1

		total_result[result.card_from] = {}
		total_result[result.card_from].xiaohu_hu_pao = 1
	end

	self:set_total_resut(total_result)

	if not self.game.xiao_hu_result then
		self.game.xiao_hu_result = {}
	end

	table.insert(self.game.xiao_hu_result,ret.mj_xiao_hu_result_res)
	if not next(self.game.xiao_hu) then
		return self:enter_tian_hu_state()
	end
end

function Machine:calculate_result(result,tag)
	log.debug("进入 calculate_result阶段,游戏结束",result)
	self:set_game_state(self.game_status.STATE_GAME_OVER)

	local message = {}
	message.card_result = self:get_player_cards()
	message.dealer = self.game.dealer
	--计算下一局庄家
	local next_dealer = 0
	local score_result = {}

	local info = {}
	local tab = {}
	if not result then
		--message.winner = {}
		message.win_info = {}
	
	else
	
		if tag then
			for k,v in pairs(result) do
				table.insert(tab,v)
				next_dealer = v.card_from
			end	
		else
			table.insert(tab,result)
		end
		message.win_info,info = self:result(tab)
		self:log_debug(info,"result info")
	end
	
	message.base_score   = info.base_score
--	message.winner       = info.winner
	message.xiao_hu      = self.game.xiao_hu_result
	message.score_result = info.score_result or {}
	message.fish_cards   = self.game.fish_cards
	message.award_card   = self.game.award_fish_cards
	message.total_result = {}
	message.left_cards 	 = self.game.set
	local total_result 	 = {}
	for k,v in pairs(self.player) do
		if not total_result[k] then
			total_result[k] = {}
		end
		total_result[k].total_score = self.player[k]:get_score()

		if not result then
			message.score_result[k] = 0
		end
		message.total_result[k] = self.player[k]:get_score()
	end

	message.xiao_hu_socre = self.game.xiao_hu_socre
	--把分数加入到玩家信息中
	for k,v in pairs(message.score_result) do
		local player = self:getPlayerBySeat(k)
		if player then
			player.chip = player.chip + v
		end
	end

	local ret = {
	 mj_result_res = message
	}
	self:log_error(ret,nil,32)
	self:sendToAll(ret)

	for k,data in pairs(tab) do
		if data.card_from == 0 then
			if not total_result[data.user].self_hu then
				total_result[data.user].self_hu = 0
			end
			total_result[data.user].self_hu = total_result[data.user].self_hu + 1
		else
			if not total_result[data.user] then
				total_result[data.user] = {}
			end
			if not total_result[data.card_from] then
				total_result[data.card_from] = {}
			end
			if not total_result[data.user].hu then
				total_result[data.user].hu = 0
			end
			total_result[data.user].hu = total_result[data.user].hu + 1

			if not total_result[data.card_from].hu_pao then
				total_result[data.card_from].hu_pao = 0
			end
			total_result[data.card_from].hu_pao = total_result[data.card_from].hu_pao + 1
		end
	end

	--统计总结算
	self:set_total_resut(total_result)

	for seatid,playerid in pairs(self.seat_list) do 
		player = self.player_list[playerid]
		player.ready = false
	end
	
	for k,v in pairs(message.card_result) do
		local player = self:getPlayerBySeat(k)
		if player then
			v.playerid = player.playerid
		end
	end


	self.game.log.result = {message}

	--计算玩家的得分 统计玩家输赢
	local callback2 = function ( )		
		self.fsm:fire("to_rest")			
	end
	local timehandler = self.timer:register(2,nil,callback2)
	self:record_game_log(message)
end

function Machine:result(result)
	local ret = {}
	local msg = {}
	--msg.winner = {}
	msg.score_result = {}
	msg.award_card = {}
	for i=1,self.config.player_num do
		msg.score_result[i] = 0
	end
	for k,v in pairs(result) do
		ret[k] = {}
		ret[k].winner =v.user
		local t = self:get_pai_xing_info(v) or {}
		t.chi = self.player[v.user]:is_chi()
		t.hu_type,t.base,t.sp_hu = card:check_hu_type(t)
		local base_score = self:get_base_score(v,t)

		ret[k].pai_xing = self:get_pai_xing(t)

		local fish_cards,award_cards = self:get_fish_card(v)
		--local fish_num = #award_cards
		msg.fish_cards = fish_cards
		self.game.fish_cards = fish_cards
		table.insert(msg.award_card,{cards = award_cards}) 
		local score_result = self:calculate_score(v,base_score,award_cards)
		for k,v in pairs(score_result) do
			msg.score_result[k] = msg.score_result[k] + v
		end
		ret[k].card_from = v.card_from 
		ret[k].card = v.recent_get
	end
	return ret , msg
end

function Machine:get_fish_num(winner,loser,award_cards)
	local win = 0
	if next(award_cards[winner]) then
		win = win + #award_cards[winner].cards
	end
	if next(award_cards[loser]) then
		win = win + #award_cards[loser].cards
	end

	return (win == 0) and 1 or ( math.ceil (2 ^ (win ) )) 
end

function Machine:calculate_score(result,base_score,award_cards)
	local dealer_score = 1
	local score_result = {}
	local winner_score = 0
	if result.card_from == 0 then
		local other = result.user
		for i=1,#self.player - 1 do
			local score = base_score
			other = other%#self.player + 1
			-- local t = {}
			-- t.winner = result.user
			-- t.other = other
			-- t.base_score = base_score
			-- score = self:zi_mo_calculate_score(t)
			local fish_num = self:get_fish_num(result.user,other,award_cards)
			if other == self.game.dealer or result.user == self.game.dealer then
				score = score + dealer_score
			end
			score = score * (fish_num)
			winner_score = winner_score + score
			self.player[other]:add_score(- score)
			score_result[other]= - score
		end
		score_result[result.user] = winner_score
		self.player[result.user]:add_score(winner_score)
	else
		local other = result.user
		for i=1,#self.player - 1 do
			local score = base_score
			other = other%#self.player + 1
			local t = {}
			t.winner = result.user
			t.card_from = result.card_from
			t.other = other
			t.base_score = base_score
			score = self:fang_pao_calculate_score(t)
			local fish_num = self:get_fish_num(result.user,other,award_cards)
			if score ~= 0 and ( other == self.game.dealer or result.user == self.game.dealer ) then
				score = score + dealer_score
			end
			score = score * (fish_num)

			winner_score = winner_score + score
			self.player[other]:add_score(- score)
			score_result[other]= - score
		end
		score_result[result.user] = winner_score
		self.player[result.user]:add_score(winner_score)
	end
	return score_result
end

function Machine:fang_pao_calculate_score(t)
	local score = 0
	if t.other == t.winner then
		score = 0
	elseif t.other == t.card_from then
		score = t.base_score
	elseif t.other ~= t.card_from then 
		score = 0
	else
		score = 0
	end
	return score
end

function Machine:get_base_score(v,t)
	local base_score = 0
	if t.base then
		if #t.sp_hu > 0 then
			base_score = 3 * #t.sp_hu
		else
			base_score = 1
		end
	else
		base_score = 3 * #t.hu_type + 3 * #t.sp_hu
	end
	return base_score
end

function Machine:get_fish_card(winner)
	local all_fish_cards = {}
	local award_fish_cards = {{},{},{},{}}
	local index = self.game.men_feng[winner]
	local num = 0
	if not self.game.fish_cards then
		for k,v in pairs(self.game.set) do
			if num >= self.config.fish_num then
				break
			end
			table.insert(all_fish_cards, v)
			num = num + 1
		end
	end
	if self.game.fish_cards then
		all_fish_cards = self.game.fish_cards
	end

	local rotation_card = {[1] = 1,[2] = 2,[3] = 3,[4] = 4,[5] = 1,[6] = 2,[7] = 3,[8] = 4,[9] = 1}
	if not self.game.award_fish_cards then
		for k,v in pairs(all_fish_cards) do
			local sid = rotation_card[card:get_value(v)]
			if sid then
				if not award_fish_cards[sid].cards then
					award_fish_cards[sid].cards = {}
				end
				table.insert(award_fish_cards[sid].cards,v)
			end
		end
		self.game.award_fish_cards = award_fish_cards
	end
	local award_cards = {}
	if award_fish_cards[winner] then
		award_cards = award_fish_cards[winner].cards
	end
	return all_fish_cards,award_fish_cards
end

function Machine:get_pai_xing(t)
	local hu = {}
	local pai_xing = {}
	card:add(hu,t.hu_type)
	card:add(hu,t.sp_hu)
	for i=1,16 do
        pai_xing[i]=0
        for k,v in pairs(hu) do
            if i == v then
                pai_xing[i] = 3
                if i == 1 then
                	pai_xing[i] = 1
                end
            end
        end
    end

	return pai_xing
end

function Machine:get_pai_xing_info(v)
	local t = {}
	t.set = self.player[v.user]:get_set()
	card:sort_card(t.set)
	t.all_set = self.player[v.user]:get_all_card()
	card:sort_card(t.all_set)
	local set = self.player[v.user]:get_set()

	if v.card_from ~= 0 then
		table.insert(t.all_set,v.recent_get)
	end

	if self.config.hai_di_hu == 1 and self:get_left_card_num() == 0 then
		if v.card_from == 0 then
    		t.hai_di_lao_yue = true
    	else
    		t.hai_di_pao = true
    	end
    end

	if self.game.qiang_gang then
		t.qiang_gang_hu = true
		self.game.gang_shang_flower = 0
	end

	if self.game.gang_shang_flower ~= 0 then
		if v.card_from == 0 then
       		t.gang_shang_flower = true
       	else
       		t.gang_shang_pao = true
       	end
    end

    if #v.set == 2 and v.set[1] == v.set[2] and #self.player[v.user]:get_black_gang_set() < 1 then
		t.quan_qiu_ren = true
	end
    if self.game.check_tianhu then
       	t.tian_hu = true
    end
    if self.game.first_card then
       	t.di_hu = true
    end

	return t
end

function Machine:get_player_cards()
	local ret = {}
	for k,v in pairs(self.player) do
		local card_info = v:get_result_set()
		card_info.seatid = k
		table.insert(ret,card_info)
	end
	return ret
end

function Machine:get_ting_data(target,c)
	local ret = {}
	local ting = self:get_ting_result(target,c)
	local ting_num = {}
	if next(ting) then
		ting_num = self:get_ting_num(target)
	end
	for k,v in pairs(ting) do
		local tb = {play = k}
		tb.hudata = {}
		for x,y in pairs(v) do
			local num = (ting_num[x]) and 4 - ting_num[x] or 4
			table.insert(tb.hudata,{card=x,score=y.score,pai_xing=y.type,nums=num})
		end
		table.insert(ret,tb)
	end

	return ret
end

function Machine:get_ting_result(target,c)
	local ting = {}

	local tb = {}
	local plr = self.player[target]
	tb.set = table_copy_table(plr:get_set())
	local c = plr:get_this_turn_get() or c
	if c then
		card:add(tb.set,c)
	end
	tb.chi = plr:get_chi_ting()	--吃的牌
	tb.peng = plr:get_peng_ting() --碰的牌
	tb.gang = plr:get_gang_ting() --杠的牌
	tb.tb = {}
	tb.tb.need_258 = ( plr:need_258())
	tb.tb.chi = plr:is_chi()
	ting = ting_pai:get_ting(tb)

	return ting
end

function Machine:player_take_card_after_gang(target)
	self.game.turn = target
	local c = self:take_card_from_end_gang()
	if not c then
		return
	end
	self:deal_player_take_card(target,c)
end

--如果只有一张牌了还要不要杠摇
function Machine:enter_take_card_gang_yao(target)
	log.debug("进入 on_gang_yao(杠摇),摸牌并判断阶段")
	self:set_game_state(self.game_status.STATE_GANG_YAO)
	self.game.turn = target

	self.game.gang_shang_flower = self.game.turn
	local cards = {}
	for i=1,self.config.gang_yao_num do--table.remove(self.game.set,1)
		table.insert(cards,self:take_card_from_end_gang())
	end
	if not next(cards) then
		return
	end
	--self:deal_player_take_card(target,c)
	--设置玩家的状态(托管) 如果能胡就就牌并把不能胡的牌打出去

	table.insert(self.game.gang_yao_data.player,target)

	local log = {cmd="gang_yao",seatid=target,cards=cards}
	self:set_game_log(log)
	local x,y = self:get_card_dice() --骰子
	self:send_take_card_message(target,nil,cards,x,y)

	--判断自己能不能胡 并且把自己不能胡的牌加入到其他玩家胡牌的列表中
	local other_check = {}
	local plr = self.player[target]
	local set  = plr:get_set()
	local result = {}
	for k,v in pairs(cards) do
		local set_t = table_copy_table(set)
		card:add(set_t,v)
		local tb = {}
		tb.need_258 = ( plr:need_258())
		tb.chi = plr:is_chi()
		local tp = card:check_hu_var(set_t,tb)
		if tp then
			local msg = {user = target,tp = tp,set = set_t,recent_get = v,card_from = 0}
			table.insert(result,msg)
		else
			table.insert(other_check,v)
		end
	end

	--如果自己胡了 把不能打的牌打出去判断其他人是否能胡
	if #result > 0 then
		--如果没有剩下牌 直接结算
		--如果有剩下牌 判断其他人呢是否可以胡牌
		if #other_check ~= 0 then
			--判断其他人是否可以胡
			local other = target
			for k,v in pairs(other_check) do
				for i=1,#self.player - 1 do
					other = other%#self.player + 1
					local plr = self.player[other]
					local set  = plr:get_set()
					local set_t = table_copy_table(set)
					card:add(set_t,v)
					local tb = {}
					tb.need_258 = ( plr:need_258())
					tb.chi = plr:is_chi()
					local tp = card:check_hu_var(set_t,tb)
					if tp then
						local msg = {user = other,tp = tp,set = set_t,recent_get = v,card_from = target}
						table.insert(result,msg)
					end
				end
			end
		end
		local tag = nil
		if #result ~= 1 then
			tag = true
		else
			result = result[1]
		end

		local callback = function()
			self:calculate_result(result,tag)
		end
		self:setTime(4,callback)
		return 
	else
		
		for k,v in pairs(other_check) do
			self.player[target]:gang_yao_play(v)
		end
		--自己没胡需要判断其他能是否可以吃碰杠胡
		local target = target
		local c = other_check[#other_check]

		self.game.recent_play.target = target
		self.game.recent_play.card = c

		local callback = function()
			self:enter_wait_reponse_card_state(target,c)
		end
		self:setTime(2,callback)
		return 
	end
end

-----------------------------------------------------------------------------
--玩家操作
-----------------------------------------------------------------------------
--过 self.game.status ~= self.game_status.STATE_DEAL_POKER
function Machine:sameone_hai_di(target,yes)
	if yes then
		for i,v in ipairs(self.player) do
			self.player[i]:set_action_can_do({})
		end
		--self.game.hai_di = true
		--玩家摸牌
		local c = table.remove(self.game.set,1)
		self.game.gang_shang_flower = 0
		self:send_left_card_num_message(self:get_left_card_num()+1)
		
		local plr = self.player[target]
		plr:set_this_turn_get(c)
		self:send_take_card_message(target,c)
		--结果判断
		local set = self.player[target]:get_set()
		local set_t = table_copy_table(set)
		card:add(set_t,c)
		local tb = {}
		tb.need_258 = ( plr:need_258())
		tb.chi = plr:is_chi()
		local tp = card:check_hu_var(set_t,tb)
		if tp then
			local message = {user = target,tp = tp,set = set_t,recent_get = c,card_from = 0 }
			return self:calculate_result(message)
		else

			return self:enter_wait_play_state(target)
		end
	end

	local next_target = target%#self.player + 1
	log.debug("玩家 处理海底胡 玩家",target,"玩家选择",yes,"下一个询问的玩家",next_target)
	if next_target ~= self.game.hai_di.first then
		return self:deal_hai_di(next_target)
	end
	return self:calculate_result()
end
function Machine:sameone_cancel(target)
	if self.game.status ~= self.game_status.STATE_WAIT_RESPONSE and not self.game.qiang_gang and self.game.status ~= self.game_status.STATE_GANG_YAO  then
		return
	end
	self.game.cancel_action[target] = self.player[target]:get_action_can_do()
	self.player[target]:set_action_can_do({})
	self.e_p_q:remove(target)
	log.debug("============跳过成功")
	if self.e_p_q:size() == 0 then
		self:setTime()
		if self.game.qiang_gang then
			return self:continue_white_gang()
		else
			return self:player_take_card(self.game.turn%#self.player + 1)
		end
	end
	return self:is_execute_first_event()
end

function Machine:sameone_try_chi(target,t)
	if self.game.status ~= self.game_status.STATE_WAIT_RESPONSE  and self.game.status ~= self.game_status.STATE_GANG_YAO then
		log.debug("chi status error",target,t,self.game.status)
		return
	end

	if card:has(self.game.gang_yao_data.player,target) then
		log.debug("sameone_try_chi gang_yao plyer not play")
		return
	end

	self.player[target]:set_action_can_do({})
	local player = self.player[target]
	if self.e_p_q:has(target,CHI) and player:is_valid_chi(self.game.recent_play.card,t) then
		self.e_p_q:confirm(target,CHI,t)
		return self:is_execute_first_event()
	end
end

function Machine:sameone_try_peng(target,c)
	if self.game.status ~= self.game_status.STATE_WAIT_RESPONSE and self.game.status ~= self.game_status.STATE_GANG_YAO then
		log.debug("peng status error",target,c,self.game.status)
		return
	end

	if card:has(self.game.gang_yao_data.player,target) then
		log.debug("sameone_try_peng gang_yao plyer not play")
		return
	end

	self.player[target]:set_action_can_do({})
	local player = self.player[target]
	if self.e_p_q:has(target,PENG) then
		self.e_p_q:confirm(target,PENG)
		return self:is_execute_first_event()
	end
end


function Machine:sameone_try_hu(target)
	log.debug("sameone_try_hu status error",target,self.game.status)
	if self.game.qiang_gang then
		self:sameone_hu(target)
	elseif self.game.status == self.game_status.STATE_WAIT_PLAY then
		self:sameone_self_hu(target)
	elseif self.game.status == self.game_status.STATE_WAIT_RESPONSE then
		self:sameone_hu(target)
	elseif self.game.status == self.game_status.STATE_WAIT_XIAOHU then
		self:sameone_xiao_hu(target)
	elseif self.game.status == self.game_status.STATE_WAIT_TIANHU then
		self:sameone_tian_hu(target,true)
	elseif self.game.status == self.game_status.STATE_GANG_YAO then
		self:sameone_hu(target)
	else
		error("sameone_hu state error , target is",target)
	end
end

function Machine:sameone_hu(target)
	if self.game.status ~= self.game_status.STATE_WAIT_RESPONSE and not self.game.qiang_gang and self.game.status ~= self.game_status.STATE_GANG_YAO then
		return
	end
	if self.game.status == self.game_status.STATE_GAME_OVER then
		log.error("self.game.status is error",self.game.status,"位置",target)
		return
	end

	self.player[target]:set_action_can_do({})
	local plr = self.player[target]
	if self.e_p_q:has(target,HU) then
		self.e_p_q:confirm(target,HU)
		return self:is_execute_first_event()
	end
end

function Machine:is_execute_first_event()
	local evt = self.e_p_q:get_first_event()
	local pass = self.e_p_q:get_first_event():is_confirm()
	local wait = true
	if evt.type == HU then
		wait = self.e_p_q:is_confirm_hu()
	end
	if pass and wait then
		self:setTime()
		return self:deal_event(self.e_p_q:get_first_event())		
	end
end

function Machine:deal_event(evt)
	for i=1,#self.player do
		 self.player[i]:set_action_can_do({})
	end
	self:setTime()
	local target = evt.user
	local plr = self.player[target]
	if evt.type then
		self.data.check_dihu = false
	end
	if evt.type == HU then
		local events,users = self.e_p_q:get_all_hu()
		if #events == 1 then 
			local result = evt.message
			local log = {cmd="HU",seatid=target,cards = {result.recent_get}}
			self:set_game_log(log)
			return self:calculate_result(result)
		else
			local result = events
			for k,v in pairs(result) do	
				local log = {cmd="HU",seatid=v.user,cards = {v.recent_get}}
				self:set_game_log(log)
			end
			return self:calculate_result(result,true)
		end	
	end

	self.game.gang_shang_flower = 0
	if evt.type == CHI then
		local tb = evt.message
		local t = plr:chi(self.game.recent_play.card,tb)
		--执行听牌
		local ting = self:get_ting_data(target)
		self.player[target]:set_chi_user(self.game.turn,self.game.recent_play.card)
		if self.game.status == self.game_status.STATE_GANG_YAO then
			self.player[self.game.turn]:remove_front()
			--card:drop(self.game.gang_yao_data.handle_cards,)
		else
			self.player[self.game.turn]:remove_front()
		end

		self:send_chi_message(target,t,ting)
		local log = {cmd="CHI",seatid=target,cards = t}
		self:set_game_log(log)

		return self:enter_wait_play_state(target)
	end

	if evt.type == PENG then
		local t = plr:peng(self.game.recent_play.card)
		local ting = self:get_ting_data(target)
		self.player[target]:set_peng_user(self.game.turn,self.game.recent_play.card)
		if self.game.status == self.game_status.STATE_GANG_YAO then
			self.player[self.game.turn]:remove_front()
		else
			self.player[self.game.turn]:remove_front()
		end

		self:send_peng_message(target,t,ting)
		local log = {cmd="PENG",seatid=target,cards = t}
		self:set_game_log(log)
		return self:enter_wait_play_state(target)
	end

	if evt.type == GANG then
		self.player[target]:set_gang_user(self.game.turn,self.game.recent_play.card,target)
		local t = plr:gang(self.game.recent_play.card)
		if self.game.status == self.game_status.STATE_GANG_YAO then
			self.player[self.game.turn]:remove_front()
		else
			self.player[self.game.turn]:remove_front()
		end

		self:send_gang_message(target,t,2,evt.is_gang)
		local log = {cmd="GANG",seatid=target,cards = t}
		self:set_game_log(log)
		if evt.is_gang then
			return self:enter_take_card_gang_yao(target)
		else
			return self:player_take_card_after_gang(target)
		end
	end

end

function Machine:time_out_auto_play(target)
	if self.player[target]:get_action_can_do().hu then
		self:sameone_self_hu(target)
		return
	end

	local c = self.player[target]:auto_play()
	if not self.game.recent_play then
		self.game.recent_play = {}
	end
	self.game.recent_play.target = target
	self.game.recent_play.card = c
	log.debug("self.game.recent_play",inspect(self.game.recent_play))
	local t = {c}
	local log = {cmd="AUTO_PLAY",seatid=target,cards=t}
	self:set_game_log(log)

	self.game.card_discard_from = target
	--广播玩家出牌 
	self:send_paly_card_message(target,c)
	--进入下一个状态

	return self:enter_wait_reponse_card_state(target,c)
end

function Machine:wait_reponse_time_out(target)
	local e = self.e_p_q:get_first_confirmed_event()
	if not e then
		return self:player_take_card(target%#self.player + 1)
	end
	self:deal_event(e)
end

function Machine:card_not_enough()	
	return self:calculate_result()
end

function Machine:sameone_try_play(tgt,c)
	if self.game.status ~= self.game_status.STATE_WAIT_PLAY then
		log.debug("play status error")
		return
	end

	if card:has(self.game.gang_yao_data.player,tgt) then
		log.debug("gang_yao plyer not play")
		return
	end

	if self.game.turn ~= tgt then
		log.debug("self.game.turn error",self.game.turn, tgt)
		return
	end

	local plr = self.player[tgt]
	if not plr:is_valid_play(c) then
		return
	end
	if not self.game.recent_play then
		self.game.recent_play = {}
	end
	self.game.recent_play.target = target
	self.game.recent_play.card = c

	self.game.card_discard_from = tgt
	self:setTime()
	plr:play_card(c)
	--通知玩家出牌

	self:send_paly_card_message(tgt,c)

	local log = {cmd="PLAY_CARD",seatid=tgt,cards = {c}}
	self:set_game_log(log)

	return self:enter_wait_reponse_card_state(tgt,c)
end

function Machine:sameone_gang(target,c,is_gang)
	log.debug("sameone_gang status",target,c,self.game.status)
	if self.game.status == self.game_status.STATE_WAIT_RESPONSE then
		self:sameone_try_gang(target,c,is_gang)
	elseif self.game.status == self.game_status.STATE_WAIT_PLAY then
		local player = self.player[target]
		local peng_user = player:get_peng_user()
		if peng_user[c] then
			self:sameone_white_gang(target,c,is_gang)
		else
			self:sameone_black_gang(target,c,is_gang)
		end
	elseif self.game.status == self.game_status.STATE_GANG_YAO then
		self:sameone_white_gang(target,c,is_gang)
	end
end

function Machine:sameone_try_gang(target,c,is_gang)
	if self.game.status ~= self.game_status.STATE_WAIT_RESPONSE then
		return
	end

	if card:has(self.game.gang_yao_data.player,target) then
		log.debug("sameone_try_gang gang_yao plyer not play")
		return
	end

	self.player[target]:set_action_can_do({})
	local player = self.player[target]
	if self.e_p_q:has(target,GANG) then
		self.e_p_q:confirm(target,GANG,nil,is_gang)
		return self:is_execute_first_event()
	end
end

function Machine:sameone_white_gang(target,c,is_gang)
	if self.game.status ~= self.game_status.STATE_WAIT_PLAY and self.game.status ~= self.game_status.STATE_GANG_YAO then
		log.error("white_gang status is not right",self.game.status)
		return
	end
	if self.game.turn ~= target then
		log.error("white_gang turn is not right",self.game.turn , target)
		return
	end
	local plr = self.player[target]
	if plr:is_valid_white_gang(c) then
		self:check_qiang_gang_hu(target,c,is_gang)
	end
end


function Machine:sameone_black_gang(target,c,is_gang)
	if self.game.status ~= self.game_status.STATE_WAIT_PLAY then
		log.error("black_gang turn is not status",self.game.status)
		return
	end
	
	if card:has(self.game.gang_yao_data.player,target) then
		log.debug("sameone_black_gang gang_yao plyer not play")
		return
	end

	if self.game.turn ~= target then
		log.error("black_gang turn is not right",self.game.turn , target)
		return
	end
	local plr = self.player[target]
	if plr:is_valid_black_gang(c) then
		local t = plr:black_gang(c)

		--self.data.men_qing_check_num[target] = self.data.men_qing_check_num[target] + 1
		local log = {cmd="BLACK_GANG",seatid=target,cards = t}
		self:set_game_log(log)
		self:setTime()
		--通知前端
		self:send_gang_message(target,t,1,is_gang)
	end
	if is_gang then
		return self:enter_take_card_gang_yao(target)
	else
		return self:player_take_card_after_gang(target)
	end
end

function Machine:check_qiang_gang_hu(target,c,is_gang)
	skynet.error("检测抢杠逻辑",target,c)
	self.game.qiang_gang = true
	local e_p_q = event_priority_queue.new()
	e_p_q:ctor()
	--这个数据还要添加
	self.game.card_discard_from = target
	self.e_p_q = e_p_q
	local tgt = target
	for i=1,#self.player - 1 do
		tgt = tgt%#self.player + 1
		--if not self.data.cancel_action[tgt].hu then
			local  t = {}
			self.player[tgt].evts = {}
			t.hu = self:check_hu(tgt,c)
			if t.hu then
				self.player[tgt]:set_action_can_do(t)
				--t.hu_card = c
				--通知前端消息
				self:send_can_reponse_message(tgt,t)
			end
		--end
	end
	self:log_error(e_p_q)
	if e_p_q:size() == 0 then
		self.game.qiang_gang = false
		local plr = self.player[target]
		local t,turn = plr:white_gang(c)

		local log = {cmd="WHITE_GANG",seatid=target,cards = t}
		self:set_game_log(log)
		self:setTime()
		--通知前端补杠消息
		self:send_gang_message(target,t,3,is_gang)
		if is_gang then
			return self:enter_take_card_gang_yao(target)
		else
			return self:player_take_card_after_gang(target)
		end
	end
	self.game.qiang_gang_data = { target = target,card = c,is_gang=is_gang }
	e_p_q:sort()
	self.game.qiang_gang = true
	local callback = function()
		self:wait_reponse_time_out(target)
	end
	self:setTime(self.status_time.oper,callback)
end

function Machine:continue_white_gang()
	self.game.qiang_gang = false
	local plr = self.player[self.game.qiang_gang_data.target]
	local t,turn = plr:white_gang(self.game.qiang_gang_data.card)

	local log = {cmd="WHITE_GANG",seatid=self.game.qiang_gang_data.target,cards = t}
	self:set_game_log(log)
	self:setTime()
	--通知前端补杠消息
	self:send_gang_message(self.game.qiang_gang_data.target,t,3,self.game.qiang_gang_data.is_gang)
	if self.game.qiang_gang_data.is_gang then
		return self:enter_take_card_gang_yao(self.game.qiang_gang_data.target)
	else
		return self:player_take_card_after_gang(self.game.qiang_gang_data.target)

	end
end

function Machine:sameone_self_hu(target)
	if self.game.status ~= self.game_status.STATE_WAIT_PLAY then
		return
	end
	if self.game.turn == target then
		local plr = self.player[target]
		local set  = plr:get_set()
		local set_t = table_copy_table(set)
		local c = plr:get_this_turn_get()
		card:add(set_t,c)

		local tb = {}
		tb.need_258 = ( plr:need_258())
		tb.chi = plr:is_chi()
		local tp = card:check_hu_var(set_t,tb)
		if tp then

			local result = {user = target,tp = tp,set = set_t,recent_get = c,card_from = 0}

			local log = {cmd="HU",seatid=target,cards = {c}}
			self:set_game_log(log)
			self:setTime()
			--通知前端
			return self:calculate_result(result)
		end
	end
end

function Machine:sameone_xiao_hu(target)
	if self.game.status ~= self.game_status.STATE_WAIT_XIAOHU then
		log.debug("xiaohu status error",target,c,self.game.status)
		return
	end
	--self.game.xiao_hu
	if not self.game.xiao_hu[target] then
		log.debug("xiaohu data is not ex",target,self.game.xiao_hu)
		return
	end

	self.player[target]:set_action_can_do({})

	return self:calculate_xiaohu_result(target)
end

function Machine:sameone_tian_hu(target,yes)
	if self.game.status ~= self.game_status.STATE_WAIT_TIANHU then
		return
	end
	if target ~= self.game.dealer then
		return
	end
	self.player[target]:set_action_can_do({})
	self:setTime()
	if not yes then
	------------------------------------------------
	--将庄家最后一张牌设为本局刚拿的牌
		self.data.check_tianhu = false
		self.data.check_dihu = true
		self.data.first_card = true
		local set = self.player[self.game.dealer]:get_set()
		local c = table.remove(set)
		self.player[self.game.dealer]:set_this_turn_get(c)
		return self:deal_player_take_card(self.game.dealer,c)	
	end

	local log = {cmd="TIANHU",seatid=target,cards = {}}
	self:set_game_log(log)
	self:setTime()
	--通知前端
	self:calculate_result(self.tianhu)
end

function Machine:deal_player_take_card(target,c)
	log.debug("处理玩家摸牌  摸的牌为:",c,"位置:",target)
	for i,v in ipairs(self.player) do
		self.player[i]:set_action_can_do({})
	end
	if target ~= self.game.dealer then
		self.game.first_card = false
	end
	local plr = self.player[target]
	plr:set_this_turn_get(c)
	local t = {c}
	local log = {cmd="take_card",seatid=target,cards=t}
	self:set_game_log(log)

	if not c then
		return
	end

	if not self.game.first_card then
		--通知前端出牌消息
		self:send_take_card_message(target,c)
	end

	local t = {}
	local set = self.player[target]:get_set()
	local set_t = table_copy_table(set)
	card:add(set_t,c)

	local tb = {}
	if not self.game.first_card then
		tb.need_258 = ( plr:need_258())
		tb.chi = plr:is_chi()
		local tp = card:check_hu_var(set_t,tb)
		
		if tp then
			t.hu = true
		end
	end
	t.my_turn = true
	if not card:has(self.game.gang_yao_data.player,target) then
		--执行听牌算法
		local ting = self:get_ting_data(target)
		t.data = ting
		--这里杠和补字段名要换下
		local tb = {}
		local plr = self.player[target]
		tb.set = plr:get_set_ex(c)
		tb.all_set = plr:get_all_card()
		local tb1 = {}
		tb1.need_258 = ( plr:need_258())
		tb1.chi = plr:is_chi()
		if not next(ting_pai:check_ting(tb,tb1)) then
			if self.player[target]:check_gang_self() then
				t.bu = true
			end
		else
			if self.player[target]:check_gang_self() then
				t.gang = true
				t.bu = true
			end
		end
		self.player[target]:set_action_can_do(t)
	end
	--通知玩家可执行的操作
	self:send_can_reponse_message(target,t)

	return self:enter_wait_play_state(target)
end

function Machine:generate_dealer(seatid)
	if seatid and seatid ~= 0 then
		self.game.dealer = seatid
	else
		self.game.dealer = math.random(1,#self.player)
	end

	self.game.dealer = 1

	local log = {cmd="DEALER",seatid=self.game.dealer}
	table.insert(self.game.log.start,log)

	self:set_men_feng()
end

function Machine:construct_set()
	self.game.set = card:new_deck()
end

function Machine:get_card_dice()
	local x = math.random(1,6)
	local y = math.random(1,6)
	self.game.touzi.x = x
	self.game.touzi.y = y
	return x,y
end

function Machine:get_next_player(seatid)
	if not seatid then
		self.game.recent_play.target = self.game.recent_play.target%#self.player + 1
	else
		self.game.recent_play.target = seatid
	end
end

function Machine:deal_card(x,y)
	local t = {}
	for i,v in ipairs(self.player) do
		local set = {}
		local sz = 13						--发13张牌
		for j=1,sz do
			card:add(set,table.remove(self.game.set,1))
		end
		card:sort_card(set)		
		t[i] = set	
		if self:getPlayerBySeat(i) and self:getPlayerBySeat(i).playerid == 5000360 then
			--t[1] = {0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x16}
		end
	end
	--庄家再多摸一张牌
	card:add(t[self.game.dealer],self:take_card_from_start())
	--做牌
	local cards,ret = self:test_deal()
	if cards then
		t = cards
	end
	if ret then
		x = ret.x
		y = ret.y
	end
	self.game.touzi.x = x
	self.game.touzi.y = y

	for i=1,#self.player do
		self.player[i]:take_card_start(t[i]) --保存玩家的手牌到player	

		local log = {cmd="DEAL_POKER",seatid=i,cards=t[i]}
		table.insert(self.game.log.start,log)
		--发送消息给玩家--
		if self:getPlayerBySeat(1) and self:getPlayerBySeat(1).playerid == 5000361 then
			--self.game.set = {0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x15,0x17,0x16,0x15,0x17,0x16,0x15,0x17,0x16,0x15,0x17,0x16,0x15,0x17,0x16,0x15,0x17,0x16,0x15,0x17,0x16,0x15,0x17,0x16,0x15,0x17,0x16,0x15,0x17,}
			--self.game.set = {0x38,0x16,0x16,0x16}
		end
		
		local ret = {
		mj_nt_game_start_res={
			dealer = self.game.dealer,
			x = x,
			y = y,
			cards = t[i]
		}}
		local player = self:getPlayerBySeat(i)
		if player then
			self:sendMessage(player.playerid,ret)
		end
	end

end


function Machine:take_card_from_start(target)
	if self.config.hai_di_hu == 1 and #self.game.set == 1 then
		return self:enter_hai_di(target)
	end
	if #self.game.set == 0 then
		return self:card_not_enough()
	end
	self.game.gang_shang_flower = 0
	--通知玩家牌数 self:get_left_card_num() - 1
	self:send_left_card_num_message(self:get_left_card_num())
	return table.remove(self.game.set,1)
end

--这里有个bug 没牌的时候杠会卡死
function Machine:take_card_from_end_gang(target)
	if #self.game.set <= 0 then
		error("没有牌了 别摸了")
		return --self:card_not_enough()
	end
	self.game.gang_shang_flower = self.game.turn
	--通知玩家牌数 self:get_left_card_num() - 1
	self:send_left_card_num_message(self:get_left_card_num())
	return table.remove(self.game.set)
end

function Machine:get_left_card_num()
	return #self.game.set
end

function Machine:room_info(playerid)
	local player = self:getPlayer(playerid)
	local t = {}
	t.seat_player = self:getSeatPlayers()
	for k,v in pairs(t.seat_player) do
		local player = self:getPlayerBySeat(v.seatid)
		v.state = self:getPlayerState(player)
	end
	t.room_info = self:get_room_info()
	t.game_started = self:is_game_started()
	t.seatid = player.seatid
	if t.game_started then
		t.game_info = self:get_game_info(player.seatid)
	else
		t.game_info = {}
	end
	local data = {mj_room_info_res = t}
	self:log_error(data)

	if self.handlerVoteTime then 
		--在投票解散
		skynet.fork(function()
			self:nt_close_vote(playerid)
		end)
	end

	return t
end
--取桌子状态
function Machine:getTableStatus(playerid)
	local seatPlayer
	local seatPlayers = {}
	local player = self:getPlayer(playerid)

	for seatid,pid in pairs(self.seat_list) do
		if pid>0 then
			player = self.player_list[pid]			
			seatPlayer = self:getSeatPlayer(player)
			seatPlayer.oper_time = 0
			seatPlayer.state = self:getPlayerState(player)
			if seatid == self.operSeatid then --正在操作
				local operTime = self.status_time.oper - (os.time() - self.operStartTime)
				if operTime > 0 then
					-- seatPlayer.oper_time = operTime
				end
				seatPlayer.button_list = self:getPlayerOperList(player)				
			end
			if seatPlayer.playing then --正在玩有牌
				local tb = self.tbCurSeatCard[seatid]
				if tb and next(tb) then
					local tbTemp = tb
					if playerid ~= player.playerid then 	
						tbTemp = {}					
						for i=1,#tb do 
							table.insert(tbTemp,0)
						end 
					end
					seatPlayer.card_data = tbTemp
				end
				if player.look then --明牌						    
					seatPlayer.card_data  = self.tbSeatRes[seatid]
		        end
			end
			table.insert(seatPlayers,seatPlayer)
		end
	end	
	local code 
	self.curCards = {}
	if next(self.curCards) then 
		code = self.rule:getCardCode(self.curCards)
	end
	local status = {		
		seat_player = seatPlayers,
		config = self:getConfig(),
	}	
	if self.operSeatid ~= self.cardIsSeat then 
		status.cards = self.curCards
		status.card_seat = self.cardIsSeat
		status.code = code
	end		

	if self.handlerVoteTime then 
		--在投票解散
		skynet.fork(function()
			skynet.sleep(50)
			self:nt_close_vote(playerid)
		end)
	end
	log.debug("Table status################",status)	
	return status
end

--玩家状态值 
function Machine:getPlayerState(player)
	local state = 0 	
	if player.ready then 
		state = self.player_state.ready
	end	
	if player.playing then
		state = self.player_state.playing
	end
	if player.auto then
		state = self.player_state.auto
	end		
	if player.disconnect then
		state = self.player_state.disconnect
	end			
	return state
end

function Machine:sitDownCallback( playerid )
	local player = self:getPlayer(playerid)
	local seatPlayer = self:getSeatPlayer(player)	
	local data = {mj_nt_seat_change_res = {
		tableid = self.tableid,
		seatid = player.seatid,
		seat_player = seatPlayer,
		playerid = playerid,		
		leave = false,
	}}	
	self:sendToOther(playerid,data)
end

function Machine:sitUpCallback(seatid,playerid)	
	local data = {mj_nt_seat_change_res = {
		tableid = self.tableid,
		seatid = seatid,
		playerid = playerid,
		leave = true,
	}}
	self:sendToAll(data)
	self.player_list[playerid] = nil
end


function Machine:getOutCards(playerid)
	local player = self:getPlayer(playerid)
	local seatid
	local state = self:getState()
	if not player then 
		return false
	end
	seatid = player.seatid
	if not seatid or seatid == 0 then 
		return false
	end		
	return self.tbOutCard
end

function Machine:set_men_feng()
	self.game.men_feng = {}
	local target = self.game.dealer
	for i=1,4 do
		target = target%4 + 1
		self.game.men_feng[target] = i
	end
end

function Machine:set_game_state(state)
	local game_status = {
		"STATE_DEAL_POKER" 		,
		"STATE_WAIT_XIAOHU" 	,
		"STATE_WAIT_TIANHU" 	,
		"STATE_WAIT_PLAY" 		,
		"STATE_WAIT_RESPONSE" 	,
		"STATE_TAKE_CARD"		,
		"STATE_HAI_DI"			,
		"STATE_GAME_OVER"	 	,
		"STATE_GANG_YAO"	 	,
	}
	skynet.error("set_game_state",string.format("%s %s \x1b[0m", "\x1b[35m",game_status[state]))
	self.game.status = state

	local data = {mj_update_state_res={
 		state = state,	
	}}
	self:sendToAll(data)
end

function Machine:set_game_log(t)
	if not self.game.log then
		self.game.log = {}
		self.game.log.play = {}
	end
	table.insert(self.game.log.play,t)
end

function Machine:check_xiao_hu(target)
	if not self:getPlayerBySeat(target) then
		return
	end
	local plr = self.player[target]
	local set = plr:get_set()
	local c = plr:get_this_turn_get()
	local set_t = table_copy_table(set)
	card:add(set_t,c)
	
	local tb = {}
	tb.need_258 = ( plr:need_258())
	tb.chi = plr:is_chi()
	local tp = card:check_xiao_hu(set_t,tb)
	if next(tp) then
		local result = {user = target,tp = tp,set = set_t,recent_get = 0,card_from = 0}
		local t = {}
		t.xiao_hu = true
		--通知客户端小胡消息
		if not self.game.xiao_hu then
			self.game.xiao_hu = {}
		end
		self.game.xiao_hu[target] = result
		return tp
	end
end

function Machine:check_tian_hu()
	local plr = self.player[self.game.dealer]
	local set = plr:get_set()
	local c = plr:get_this_turn_get()
	local set_t = table_copy_table(set)
	card:add(set_t,c)
	
	local tb = {}
	tb.need_258 = ( plr:need_258())
	tb.chi = plr:is_chi()
	local tp = card:check_hu_var(set_t,tb)
	if tp then
		local result = {user = self.game.dealer,tp = tp,set = set_t,recent_get = c,card_from = 0}
		local t = {}
		t.my_turn = true
		t.tianhu = true
		self.player[self.game.dealer]:set_action_can_do(t)
		return result
	end
end

--------------------------------------------------------------------------------
--玩家出牌时的检测函数
--------------------------------------------------------------------------------
function Machine:check_hu(target,c)
	local plr = self.player[target]
	local set = self.player[target]:get_set()
	local set_t = table_copy_table(set)
	card:add(set_t,c)
	local tb = {}
	tb.need_258 = ( plr:need_258())
	tb.chi = plr:is_chi()
	local tp = card:check_hu_var(set_t,tb)
	if tp then
		local message = {user = target,tp = tp,set = set_t,recent_get = c,card_from = self.game.card_discard_from }
		local evt = event:new()
		evt:ctor(target,HU,tp,message)
		self.e_p_q:insert(evt)
		return true
	end
end

function Machine:check_peng(target,c)
	local set = self.player[target]:get_set()
	if card:check_peng(set,c) then
		local evt = event:new()
		evt:ctor(target,PENG)
		self.e_p_q:insert(evt)
		return true
	end
end

function Machine:check_gang(target,c)
	local set = self.player[target]:get_set() 
	if card:check_gang(set,c) then
		local evt = event:new()
		evt:ctor(target,GANG)
		self.e_p_q:insert(evt)
		return true
	end
end

function Machine:check_chi(target,c)
	local set = self.player[target]:get_set()
	if card:check_chi(set,nil,c) then
		local evt = event:new()
		evt:ctor(target,CHI)
		self.e_p_q:insert(evt)
		return true
	end
end

--加入玩家
function Machine:can_join(playerid)
	local num = 0 
	for k,v in pairs(self.player_list) do 
		if k ~= self.config.owner then 
			num = num + 1
		end
	end
	if num >= self.config.player_num - 1  and playerid ~= self.config.owner then 
		return false
	end
	return true
end

--加入玩家
function Machine:add_player(player)
	self:readUserInfo(player)
	self:read_user_gains(player)
	if self.config.owner == player.playerid then 
		self.manager = table.copy(player)
	end
	player.chip = 0
	self.player_list[player.playerid] = player
	self:updatePlayerNum()
end

--离开桌子
function Machine:leave_table(playerid)
	local player = self:getPlayer(playerid)
	if self.data.ordinal>0 and self.game.status ~= self.game_status.STATE_GAME_OVER then 
		return false
	end
	log.debug('玩家离开牌桌>>>>>>>>>>>',playerid,self.config.owner,self.tableid)
	if playerid == self.config.owner then	
		--房主位置不清除
		player.ready = false		
		self:nt_disconnect(playerid)
		return true
	else
		--aa支付
		if self.data.ordinal == 0 and self.payer==2 then 
			--返卡
			if player.ready then 
				local fangka = self:callGate(player, 'change_fangka', self.config.cost, reason)		
				if fangka then 				
				end				
			end
		end		
	end
	
	self:sitUp(playerid)
	self.player_list[playerid] = nil
	self:updatePlayerNum()
	return true
end

function Machine:player_ready( playerid )
	local player = self:getPlayer(playerid)
	local seatid
	local state
	if not player then 
		log.error("not player")
		return false
	end
	seatid = player.seatid
	if not seatid or seatid == 0 then 
		log.error("not seatid")
		return false
	end
	player.ready = true
	
	--aa支付
	if self.data.ordinal == 0 and self.config.pay_type==2 then 
		--扣卡
		if playerid ~= self.config.owner then 
			local ok = self:callGate(player, 'change_fangka', -self.config.cost, reason)		
			if not ok then 	
				log.error("not change_fangka")	
				return false	
			end				
		end
	end
	local data = {
		mj_ready_res = {
			succese = true,
			seatid = seatid
		}
	}
	self:sendToAll(data)
	return true
end

--桌子相关配置
function Machine:getConfig()
	return {
		bottom_num	= 1,--self.bottomNum,	-- 底分		
		time_wait = 1, -- self.status_time.wait,
		time_rest = 5,--self.status_time.rest,
		time_start = 4,--self.status_time.start,
		time_end = 1,-- self.status_time.settlement,	
		time_oper =10,-- self.status_time.oper,
		card_num = 15,-- self.cardNum,
		max_jushu =16,-- self.maxJuShu,
		cur_jushu = 0,-- self.curJuShu,
		table_num = self.config.verify_code,
		managerid = 5000294,-- self.config.owner,
		pay_type = 1,-- self.payer,
		close_time =300,-- self.maxWaitTime-self.waitTime,
	}
end
-------------------------------------------------------------------------------
function Machine:nt_start()
	local data = {pdk_nt_start={
 		tableid = self.tableid,	
 		paijuid = self.paijuid,
 		seatid = self.startSeatid,
 		first_card = self.firstCard,
	}}
	self:sendToNoSeat(data)
end

function Machine:nt_rest()
	local data = {pdk_nt_rest={
 		tableid = self.tableid,	
	}}
	self:sendToAll(data)	

end

--总结算通知
function Machine:nt_total_result()

	self.fangkaEnd = true
	local data = {{},{},{},{}}
	for k,v in pairs(self.data.total_result) do
		local player = self:getPlayerBySeat(k)
		data[k].self_hu 		= v.self_hu
		data[k].xiaohu_zimo 	= v.xiaohu_zimo
		data[k].hu_pao 			= v.hu_pao
		data[k].xiaohu_hu_pao 	= v.xiaohu_hu_pao
		data[k].hu 				= v.hu
		data[k].xiaohu_hu 		= v.xiaohu_hu
		if player then
			data[k].total_score 	= player.chip
			data[k].playerid 		= player.playerid
			data[k].name 			= player.nick
			data[k].head 			= player.icon
			data[k].seatid 			= k
		end
	end
	--TODO 协议替换 pdk_nt_fanka_end
	local data = {mj_total_result_res={
 		data = data,
 		verify_code = self.config.verify_code,	
 		ordinal = self.data.ordinal,
 		total_ordinal = end_players,
 		time = os.time(),
 		owner = self.config.owner
	}}	
	self:sendToAll(data)	
	self:log_error(data,"nt_total_result",32)

	--把所有人踢出房间后关闭服务
	self.nodeMessage:callGlobalService('tablestate','close_private',playerid, self.tableid)	
	self:close_room()	
end

function Machine:nt_ready(playerid,seatid)	
	local seatPlayer = {seatid=seatid,state=self.player_state.ready}
	local data = {mj_nt_seat_change_res={
 		tableid = self.tableid,			 		
 		seat_player = seatPlayer, 	
 		playerid = playerid,	
 		seatid = seatid,
	}}	

	self:sendToAll(data)	
	return true,seatid		
end

--掉线处理
function Machine:disconnect(playerid)	
	local player = self.player_list[playerid]
	local seatid = player.seatid
	log.debug('玩家掉线>>>>>>>>>>>',playerid,self.config.owner,self.tableid,player.playing,player.disconnect)
	if  playerid==self.config.owner then 
		log.debug("disconnect房主不能离开桌子")		
		self:nt_disconnect(playerid)		
		return false
	end
	--旁观者掉线马上踢出大厅,房主不能离开桌子
	if self.data.ordinal==0 and not player.playing and player.disconnect then 
		log.debug("########在旁观玩家中直接踢走")	
		-- self:sendGate(player, 'update_tableid', 0)
		-- self:sitUp(playerid)
		-- self.player_list[playerid] = nil

		-- local sql = string.format("delete from user_online where uid = %d;", k)
		-- skynet.send("mysql_service", "lua", "execute", sql)	
		return false
	else
		self:nt_disconnect(playerid)			
	end	
	return false
end

function Machine:nt_disconnect(playerid)
	local player = self:getPlayer(playerid)
	local seatid = player.seatid
	local seatPlayer = self:getSeatPlayer(player)
	if not seatPlayer then
		seatPlayer = {}
	end
	seatPlayer.state=self.player_state.disconnect
	local data = {mj_nt_seat_change_res={
 		tableid = self.tableid,			 		
 		seat_player = seatPlayer, 	
 		playerid = playerid,	
 		seatid = seatid,
	}}	
	self:sendToOther(playerid,data)
end

function Machine:nt_onconnect(playerid)
	local player = self:getPlayer(playerid)
	local seatid = player.seatid
	if not seatid or seatid==0 then 
		return 
	end
	local seatPlayer = self:getSeatPlayer(player)
	if not seatPlayer then
		seatPlayer = {}
	end
	seatPlayer.state=self.player_state.playing
	local data = {mj_nt_seat_change_res={
 		tableid = self.tableid,			 		
 		seat_player = seatPlayer, 	
 		playerid = playerid,	
 		seatid = seatid,
	}}	
	self:sendToOther(playerid,data)	
end

--激活关桌子
function Machine:close_private_room(playerid)
	if self.data.ordinal==0 and playerid~=self.config.owner then 
		return false
	end
	--没开局直接解散，开局后要投票
	if self.data.ordinal > 0 then 
		--self.vote.tbCloseVote[playerid] = 1
		--self:nt_close_vote()
		--self.fsm2:fire("to_start")
		self:sameone_vote_result(playerid,{agree=true},true)
		return false
	else
		self:deleteTable(self.config.owner)
	end
	return true
end

--同意关桌子
function Machine:sameone_vote_result(playerid,args,flag)
	if not flag and not next(self.vote.tbCloseVote) then
		return
	end
	if next(self.vote.tbCloseVote) then
		if self.vote.tbCloseVote[playerid] then  
			return false
		end
	else
		self.sourceid = playerid
		self.fsm2:fire("to_start")
	end
	if args.agree then 
		self.vote.tbCloseVote[playerid] = 1
	else
		self.vote.tbCloseVote[playerid] = 2 --拒绝
	end
	local allClose = true
	for k,v in pairs(self.player_list) do 
		if not v.disconnect then 
			if not self.vote.tbCloseVote[k] or self.vote.tbCloseVote[k]==2 then 
				allClose = false
				break
			end
		end
	end
	if allClose then 
		--所有已关闭，解散桌子
		self.fsm2:fire("to_end")
	else
		--通知同意的人数增加了
		log.debug("nt_close_vote",playerid,self.sourceid)
		if playerid == self.sourceid then
			self:nt_close_vote()	
		else
			self:nt_vote_result(playerid,args.agree)
		end
		--判断是不是所有人都选择了
		if self.vote.tbCloseVote[playerid]==2 then
			self.fsm2:fire("to_rest")
		end	
	end

	return true
end

function Machine:nt_vote_result(playerid,agree)
	local data = {mj_vote_result_res={
		playerid = playerid,
 		succese = agree 
	}}	
	self:sendToAll(data)
end

--投票解散
function Machine:nt_close_vote(playerid)	
	local tbPlayer={}
	local player={}
	for k,v in pairs(self.player_list) do 
		player = {}
		player.nick = v.nick
		player.seatid = v.seatid
		player.playerid = v.playerid
		player.chip = v.chip
		player.diamond = v.diamond
		player.agree = self.vote.tbCloseVote[k] or 0
		player.icon = v.icon
		table.insert(tbPlayer,player)
	end
	local data = {mj_nt_close_vote_res={
 		tableid = self.tableid,	
 		vote_player = tbPlayer,
 		time = self.closeVoteTime,
 		managerid = self.config.owner,
 		sourceid = self.sourceid,
	}}	
	if playerid then
		self:sendMessage(playerid,data)
	else
		self:sendToAll(data)
	end
	log.debug("____mj_nt_close_vote_res____",data)

end

function Machine:close_room()
	--把所有人踢出房间后关闭服务
	for k,v in pairs(self.player_list) do 	
		--设置玩家所在桌子id为0	
		self:sendGate(v, 'update_tableid', 0)
		self:sitUp(k)
		self.player_list[k] = nil
		self:updatePlayerNum()	
		local sql = string.format("delete from user_online where uid = %d;", k)
		skynet.send("mysql_service", "lua", "execute", sql)	
	end
	self:exit()	
end
--删除桌子
function Machine:deleteTable(playerid)
	local data = {nt_manager_close={
		playerid=playerid,
		tableid=self.tableid,
	}}
	self:sendToAll(data)
	log.debug("_______closePrivate___",data)
	self.fangkaEnd = true
		
	--返还房卡
	local player = self:getPlayer(playerid)
	if player then 
		--在房间中
		local fangka = self:callGate(player, 'change_fangka', self.config.cost, reason)		
		if not fangka then --玩家不在线直接改数据库
			local sql = string.format("update usergame set room_ticket=room_ticket + %d where uid=%d",
				self.config.cost,playerid)		
			self.nodeMessage:sendService("mysql_service","execute", sql)		
		end
		for k,v in pairs(self.player_list) do 			
			--aa支付
			if k~=self.config.owner and self.payer==2 then 
				--返卡
				if v.ready then 
					local fangka = self:callGate(v, 'change_fangka', self.config.cost, reason)		
					if fangka then 	
						local sql = string.format("update usergame set room_ticket=room_ticket + %d where uid=%d",
							self.config.cost,k)		
						self.nodeMessage:sendService("mysql_service","execute", sql)								
					end				
				end
			end	
		end

		self.nodeMessage:callGlobalService('tablestate','close_private',playerid, self.tableid)	
		self:close_room()		
	else
		--重启服务器，会出现这种情况 只改数据库
		for k,v in pairs(self.player_list) do 			
			--aa支付
			if k~=self.config.owner and self.payer==2 then 
				--返卡
				if v.ready then 
					local fangka = self:callGate(v, 'change_fangka', self.config.cost, reason)		
					if fangka then 	
						local sql = string.format("update usergame set room_ticket=room_ticket + %d where uid=%d",
							self.config.cost,k)		
						self.nodeMessage:sendService("mysql_service","execute", sql)								
					end				
				end
			end	
		end		

		self.nodeMessage:callGlobalService('tablestate','close_private',playerid, self.tableid)	
		self:close_room()		
	end

end

function Machine:read_user_gains(player)
	local sql = string.format("select * from user_gains_data where uid=%d and `game`=%d and `gameid`=%d and `gametype`=%d",player.playerid,player.game,self.gameid,self.config.lose_type)
	local res = self.nodeMessage:callService("mysql_service",'execute',sql)
	if res and next(res) then
		self.data.user_gains = res[1]
	else
		self.data.user_gains={
			wincnt = 0, losecnt = 0, drawcnt = 0, win_streak = 0, cur_win_streak = 0, best_id = 0, best_score = 0, gains_info = " "
		}
		local user_gains = self.data.user_gains
		local str = "user_gains_data (wincnt, losecnt, drawcnt, `win_streak`, cur_win_streak, best_id, `best_score`, gains_info,uid,game,gameid,gametype)"
		local sql = string.format([[insert into %s values (%d, %d, %d, %d, %d, %d, %d, '%s' ,%d, %d, %d, %d)]],str,
	                                        user_gains.wincnt, user_gains.losecnt, user_gains.drawcnt, user_gains.win_streak, 
	                                        user_gains.cur_win_streak, user_gains.best_id, user_gains.best_score, user_gains.gains_info,
	                                        player.playerid,player.game,self.gameid,self.config.lose_type)

		self:log_error(sql)
		local res = self.nodeMessage:callService("mysql_service",'execute',sql)
	end
end

function Machine:record_user_gains(t)
	local user_gains = self.data.user_gains
	local win_score = t.win_score
	if win_score > 0 then 
		user_gains.wincnt = user_gains.wincnt + 1
		user_gains.cur_win_streak = user_gains.cur_win_streak + 1
		if user_gains.cur_win_streak >= user_gains.win_streak then
			user_gains.win_streak = user_gains.cur_win_streak
		end
	else
		user_gains.losecnt = user_gains.losecnt + 1
		user_gains.cur_win_streak = 0
	end
	if not next(t.win_info) then
		user_gains.drawcnt = user_gains.drawcnt + 1
		user_gains.cur_win_streak = 0
	end
	if win_score >= user_gains.best_score then
		user_gains.best_id = t.tlid
		user_gains.gains_info = json.encode(t.gains_info)
	end
	--
--[[		replace into user_gains_data (wincnt, losecnt, drawcnt, `win_streak`, cur_win_streak, best_id, `best_score`, gains_info) 
		values(%d, %d, %d, %d, %d, %d, %d, %s) 
		WHERE uid=%d and `game`=%d and `gameid`=%d and ]]
	local sql = string.format([[update user_gains_data set wincnt=%d, losecnt=%d, drawcnt=%d, `win_streak`=%d, cur_win_streak=%d, best_id=%d, `best_score`=%d, gains_info='%s' where  uid=%d and `game`=%d and `gameid`=%d and `gametype`=%d;]],
		user_gains.wincnt, user_gains.losecnt, user_gains.drawcnt, user_gains.win_streak, user_gains.cur_win_streak, user_gains.best_id, user_gains.best_score, 
		user_gains.gains_info,player.playerid,player.game,self.gameid,self.config.lose_type)
	self:log_error(sql)
	skynet.send("mysql_service", "lua", "execute", sql)	

end
--牌局记录 
function Machine:record_game_log(message)
	local table_name = 'qclandlord_tablelog'
	local str = table_name .." (tid,trdid,svid,tlcnt,tllog,tltime,game,gameid,gametype,room_owner,room_flag)"

	local time = os.time()
	self.game.log.game_config.end_time = time

	local tllog = json.encode(self.game.log)
	if not tllog or tllog=='' then
	end
	local sql = string.format("insert into %s value(%d,%d,%d,%d,'%s',%d,%d,%d,%d,%d,%d)",
		str,self.tableid,self.data.ordinal,11,self.config.player_num,tllog,os.time(),5,self.gameid,self.roomid,self.config.owner or 0,self.room_flag)

	local res = skynet.call("mysql_log", "lua", "execute", sql)
	if not res then 
		return 
	end

	local tlid = res.insert_id
	if not tlid then 
		return
	end

	for k, v in pairs(self.player) do
		local wlfold = 0
		local player = self:getPlayerBySeat(k)
		local wlwin = message.total_result[k] or 0
		local wlflag = 2 --平局
		if wlwin > 0 then
			wlflag = 1
		else
			wlflag = 0 
		end
		if player then
			local wlleft = player.chip
			local str1 = 'qclandlord_winlog' .. " (tlid, uid, pfid, usid, tid, room_id, svid, trdid, wlfold, wlleft, wlwin, wlflag, wltime, game, gameid, gametype)"
			local sql1 = string.format("insert into %s values(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);", str1, tlid, player.playerid, player.pfid or 0, player.usid or 0,self.tableid, self.roomid, 11,
						 self.data.ordinal, wlfold, wlleft, wlwin, wlflag, time, player.game or 0,self.gameid, self.roomid)
			local res = skynet.call("mysql_log", "lua", "execute", sql1)
			local win_score = message.score_result[k]
			if win_score > 0 then 
				player.uwincnt = player.uwincnt + 1
				player.cur_win_streak = player.cur_win_streak + 1
				if player.cur_win_streak >= player.win_streak then
					player.win_streak = player.cur_win_streak
				end
			elseif win_score < 0 then 
				player.ulosecnt = player.ulosecnt + 1
				player.cur_win_streak = 0
			else
				player.udrawcnt = player.udrawcnt + 1
				player.cur_win_streak = 0
			end
			self:writeUserInfo(player)

			local gains_data = {}
			gains_data.playerid = player.playerid
			gains_data.win_score = win_score
			gains_data.win_info = message.win_info
			gains_data.tlid = tlid
			gains_data.gains_info ={card_result = self.player[k]:get_result_set()}
			local pai_xing = {}
			for k,v in pairs(message.win_info) do
				if winner == k then
					gains_data.gains_info.pai_xing = v.pai_xing
				end
			end
			self:record_user_gains(gains_data)
		end
	end
end

function Machine:get_room_info(playerid)
	local t = {}
	t.owner = self.config.owner
	t.fish_num = self.config.fish_num
	t.player_num = self.config.player_num
	t.verify_code = self.config.verify_code
	t.ordinal = self.data.ordinal
	t.play_count = self.config.play_count
	t.base_score = self.config.base_score
	t.pay_type = self.config.pay_type
	t.play_time = self.status_time.oper
	t.close_time = self.time.close_room_time - self.waitTime
	return t
end

function Machine:get_game_info(seatid)
	local t = {}
	t.dealer = self.game.dealer
	t.state  = self.game.status
	t.turn   = self.game.turn
	t.player_set,t.can_reponse = self:get_player_set(seatid)
	t.left_card = self:get_left_card_num()
	t.card_to_handle = self.game.recent_play.card or 0
	t.left_time = self:get_timer_left_time()
	t.turn_card = self.player[seatid]:get_this_turn_get()
	t.handle_tgt = self.game.recent_play.target or 0
	return t
end

function Machine:get_seat_player(playerid)
	local t = {}
	local player = self:getPlayer(playerid)
	t.playerid = playerid
	t.seatid = player.seatid

	return t

end

function Machine:send_chi_message(target,t,ting)
	local ret = {
	mj_chi_res={
		seatid = target,
		cards = t,
		card = self.game.recent_play.card
	}}

	for k,v in pairs(self.player) do
		
		if target == k then
			ret.mj_chi_res.data = ting
		else
			ret.mj_chi_res.data = nil
		end
		local player = self:getPlayerBySeat(k)
		if player then
			self:sendMessage(player.playerid,ret)
		end
	end
	self:log_error(ret,nil,32)
end

function Machine:send_peng_message(target,t,ting)
	local ret = {
	mj_peng_res={
		seatid = target,
		cards = t
	}}

	for k,v in pairs(self.player) do
		
		if target == k then
			ret.mj_peng_res.data = ting
		else
			ret.mj_peng_res.data = nil
		end
		local player = self:getPlayerBySeat(k)
		if player then
			self:sendMessage(player.playerid,ret)
		end
	end
	self:log_error(ret,nil,32)
end

function Machine:send_gang_message(target,t,_type,is_gang)
	local ret = {
	mj_gang_res={
		seatid = target,
		cards = t,
		gang_type = _type,
		is_gang = is_gang
	}}
	self:sendToAll(ret)
	self:log_error(ret,nil,32)
end

function Machine:send_take_card_message( target,c, cards,x,y)
	local ret = {
		mj_take_card_res={
			seatid = target,
			cards = cards,
			x = x,
			y = y
		}}
	for k,v in pairs(self.player) do
		
		if target == k then
			ret.mj_take_card_res.card = c
		end
		local player = self:getPlayerBySeat(k)
		if player then
			self:sendMessage(player.playerid,ret)
		end
	end
	self:log_error(ret,nil,31)
end

function Machine:send_paly_card_message(target,c)
	local ret = {
	mj_play_card_res={
		seatid = target,
		cards = c
	}}
	self:sendToAll(ret)
	self:log_error(ret,nil,32)
end

function Machine:send_can_reponse_message(target,t )
	local ret = {
	mj_can_reponse_res=t
	}
	local player = self:getPlayerBySeat(target)

	if player then
		self:sendMessage(player.playerid,ret)
	end
	self:log_error(ret,nil,32)
end

function Machine:send_hai_di_message(target)
	local ret = {
	mj_ask_hai_di_res={seatid=target}
	}
	self:sendToAll(ret)
	--local player = self:getPlayerBySeat(target)
	if player then
		--self:sendMessage(player.playerid,ret)
	end
	self:log_error(ret,nil,32)
end

function Machine:send_left_card_num_message(num)
	local ret = {
	mj_left_card_num_res={
		num = num - 1, 
	}}
	self:sendToAll(ret)
end

function Machine:get_xiao_hu_type(tp)
	local hu_type = {}
	for i=1,8 do
		hu_type[i] = 0
		if card:has(tp,i) then
			hu_type[i] = 1
		end
	end
	return hu_type
end

function Machine:get_ting_num(target)
	local cards_num = {}
	for sid,plr in pairs(self.player) do
		if sid == target then
			local set = plr:get_all_card_and_play_front()
			for k,v in pairs(set) do
				if not cards_num[v] then
					cards_num[v] = 0
				end
				cards_num[v] = cards_num[v] + 1
			end
		else
			local set = plr:get_visible_cards()
			for k,v in pairs(set) do
				if not cards_num[v] then
					cards_num[v] = 0
				end
				cards_num[v] = cards_num[v] + 1
			end
		end
	end
	return cards_num
end

function Machine:get_player_set(seatid)
	local player_set = {}
	local can_reponse = {}
	for k,v in pairs(self.player) do
		local player = v
		local card_info = {}
		card_info.seatid = k
		card_info.set = {}
		card_info.recent_play = player:get_recent_play()
		card_info.left_card = #player:get_set()
		local chi_set = player:get_chi_set()
		card_info.chi = {}
		for k,v in pairs(chi_set) do
			local temp = {}
			temp.cards = v
	 		table.insert(card_info.chi,temp)
		end
	
		local peng_set = player:get_peng_set()
		card_info.peng = {}
		for k,v in pairs(peng_set) do
			local temp = {}
			temp.cards = v
	 		table.insert(card_info.peng,temp)
		end
	
		local gang_set = player:get_gang_set()
		card_info.gang = {}
		for k,v in pairs( gang_set) do
			local temp = {}
			temp.cards = v
	 		table.insert(card_info.gang,temp)
		end
	
		--card_info.play_front = {}--player:get_play_front()
		card_info.cards = player:get_play_front()
		if k == seatid then
			local black_gang_set = player:get_black_gang_set()
			card_info.black_gang = {}
			for k,v in pairs( black_gang_set) do
				local temp = {}
				temp.cards = v
	 			table.insert(card_info.black_gang,temp)
			end
		
			card_info.set.cards = table_copy_table(player:get_set())
			--table.insert(card_info.set.cards,player:get_this_turn_get())
			--card_info.get_this_turn = player:get_this_turn_get()
			can_reponse = player:get_action_can_do()
		else
			local black_gang_set = player:get_black_gang_set()
			card_info.black_gang = {}
			local t = {}
			for k,v in pairs( black_gang_set) do
				local temp = {}
				temp.cards = v
	 			table.insert(card_info.black_gang,temp)
			end
		end

		table.insert(player_set,card_info)
	end
	return player_set,can_reponse
end

function Machine:set_total_resut(total_result)
	if not self.data.total_result then
		self.data.total_result = {}
	end

	for k,v in pairs(total_result) do
		if not self.data.total_result[k] then
			self.data.total_result[k] = {}
		end
		if not self.data.total_result[k].self_hu then
			self.data.total_result[k].self_hu = 0
		end
		if v.self_hu then
			self.data.total_result[k].self_hu = v.self_hu + self.data.total_result[k].self_hu
		end
		if not self.data.total_result[k].xiaohu_zimo then
			self.data.total_result[k].xiaohu_zimo = 0
		end
		if v.xiaohu_zimo then
			self.data.total_result[k].xiaohu_zimo = v.xiaohu_zimo + self.data.total_result[k].xiaohu_zimo
		end
		if not self.data.total_result[k].hu_pao then
			self.data.total_result[k].hu_pao = 0
		end
		if v.hu_pao then
			self.data.total_result[k].hu_pao = v.hu_pao + self.data.total_result[k].hu_pao
		end
		if not self.data.total_result[k].xiaohu_hu_pao then
			self.data.total_result[k].xiaohu_hu_pao = 0
		end
		if v.xiaohu_hu_pao then
			self.data.total_result[k].xiaohu_hu_pao = v.xiaohu_hu_pao + self.data.total_result[k].xiaohu_hu_pao
		end
		if not self.data.total_result[k].hu then
			self.data.total_result[k].hu = 0
		end
		if v.hu then
			self.data.total_result[k].hu = v.hu + self.data.total_result[k].hu
		end
		if not self.data.total_result[k].xiaohu_hu then
			self.data.total_result[k].xiaohu_hu = 0
		end
		if v.xiaohu_hu then
			self.data.total_result[k].xiaohu_hu = v.xiaohu_hu + self.data.total_result[k].xiaohu_hu
		end
		if not self.data.total_result[k].total_score then
			self.data.total_result[k].total_score = 0
		end
		if v.total_score then
			self.data.total_result[k].total_score = v.total_score + self.data.total_result[k].total_score
		end
	end
end

function Machine:can_accept_req(playerid)
	local player = self:getPlayer(playerid)
	if not player then 
		return false
	end
	local seatid
	seatid = player.seatid
	if not seatid or seatid == 0 then
		return false
	end
	return seatid
end

function Machine:is_game_started(playerid)
	--local player = self:getPlayer(playerid)
	if not self.game.status or self.game_status.STATE_GAME_OVER == self.game.status then
		return false
	end
	return true
end


--投票解散
function Machine:startVoteCallback()
	self.closeVoteTime = self.closeVoteTime - 1
	local canClose = true
	for k,v in pairs(self.player_list) do 
		if not self.vote.tbCloseVote[k] or self.vote.tbCloseVote[k]==2 then 
			canClose = false
		end
	end
	if canClose or self.closeVoteTime==0 then 
		self.fsm2:fire("to_end")
	end
end
function Machine:onStartVote()
	self.closeVoteTime = self.voteTime
	local callback = function ()		
		self:startVoteCallback()
	end
	self.handlerVoteTime = self.timer:register(1 , nil, callback,true)	
end
function Machine:onEndVote()	
	self.timer:unregister(self.handlerVoteTime)	
	self.handlerVoteTime = nil 	
	self.nodeMessage:callGlobalService('tablestate','close_private',playerid, self.tableid)			
	self:nt_total_result()
	self:close_room()
end
function Machine:onRestVote()
	self.timer:unregister(self.handlerVoteTime)	
	self.handlerVoteTime = nil 
	self.sourceid = nil
	self.vote.tbCloseVote = {}
end

---------开始游戏
function Machine:start()
	self.fsm:set("settle")
	self.fsm:fire("to_rest")
end

function Machine:test_deal( )
	local set = {}
	local sql = "select * from make_cards where id = 1"
	local t = skynet.call("mysql_log", "lua", "execute", sql)

	if not t then
		return
	end
	
	local t = t[1]
	
	if t.isOpen ~= 1 then
		return 
	end

	local _env={set = set,last_set=self.game.set,origin_set = self.game.set,touzi=0,bai_da}
	for i=1,self.config.player_num do
		load(string.format("set[%d] = {"..t[string.format("player%d",i)].."}",i),"","t",_env)()
	end
	
	load("origin_set = {"..t["mocard"].."}","","t",_env)()
	load("touzi = {"..t["touzi"].."}","","t",_env){}
	load("bai_da = {"..t["bai_da"].."}","","t",_env){}
	load("last_set = {"..t["lastcard"].."}","","t",_env)()

	
	for k,v in ipairs(set) do
		for k1,v1 in ipairs(v) do
			if  card:get_type(v1) > 3 or card:get_type(v1) < 0 then
				if card:get_value(v1) < 0 or card:get_value(v1) > 10 then
					return
				end
			end
		end
	end
	
	local index = 1
	local c = table.remove(self.game.set)
	if t.isOpen == 1 then
		for _,v in ipairs(_env.origin_set) do
			card:remove_one_sam_card(self.game.set,v,index)
			table.insert(self.game.set,1,v)
			index = index + 1
		end
		for _,v in pairs(_env.last_set) do
			card:remove_one_sam_card(self.game.set,v,index)
			table.insert(self.game.set,v)
		end
	end

	local ret = {}
	ret.x = math.floor(_env.touzi[1]/10)
	if ret.x > 6 then
		ret.x = 6
	end
	if ret.x < 1 then
		ret.x = 1
	end
	ret.y = _env.touzi[1]%10
	if ret.y > 6 then
		ret.y = 6
	end
	if ret.y < 1 then
		ret.y = 1
	end

	local typ = card:get_type(_env.bai_da[1])
	local val = card:get_value(_env.bai_da[1])
	if typ >= 1 and typ <= 4 then
		if typ == 4 then
			if val >=1 and val <= 7 then
				ret.bai_da = _env.bai_da[1]
			end
		else
			if val >=1 and val <= 9 then
				ret.bai_da = _env.bai_da[1]
			end
		end
	end 

	if self:getPlayerBySeat(self.game.dealer) and self:getPlayerBySeat(self.game.dealer).playerid == 5000360 then
		--c = 0x17
	end
	table.insert(set[self.game.dealer],c)
	return set,ret
end

function Machine:log_debug(data,name,index)
	local color = "\x1b[32m"
	if not name or type(name) == "table" then
		name = ""
	end
	if index then
		if index <31 and index > 37 then
			index = 36
		end
		color = "\x1b["..index.."m"
	end
	log.debug(""..self.config.verify_code.." "..name,string.format("%s %s \x1b[0m", color,inspect(data)))
end

function Machine:log_error(data,name,index)
	local color = "\x1b[31m"
	if not name or type(name) == "table" then
		name = ""
	end
	if index then
		if index <31 and index > 37 then
			index = 31
		end
		color = "\x1b["..index.."m"
	end
	log.error(""..self.config.verify_code.." "..name,string.format("%s %s \x1b[0m", color,inspect(data)))
end

return Machine